package tom.vertx.core.demo07;

import io.vertx.core.AbstractVerticle;
import io.vertx.core.Promise;
import io.vertx.core.Vertx;
import io.vertx.core.VertxOptions;
import io.vertx.core.shareddata.Lock;
import io.vertx.spi.cluster.zookeeper.ZookeeperClusterManager;
import lombok.extern.slf4j.Slf4j;

/**
 * shareData可以在同一个应用、同一个vertx实例多个verticle之间，集群vertx实例间共享数据(集群依赖cluster manager)
 *    localXXX: 同应用多verticle实例间共享
 *    asyncXXX: 集群内多vertx实例节点间数据共享
 * @implNote
 *    集群锁、本地锁
 * @author ZHUFEIFEI
 */
@Slf4j
public class ShareData03LockDemo {

  public static void main(String[] args) {
    //本地zk
    Vertx.clusteredVertx(new VertxOptions().setClusterManager(new ZookeeperClusterManager()), res -> {
      if (res.succeeded()) {
        res.result().deployVerticle(new V1());
        log.info("vertx cluster started.");
      } else {
        log.error("vertx cluster failed.");
      }
    });
  }

  static class V1 extends AbstractVerticle {
    @Override
    public void start(Promise<Void> startPromise) throws Exception {

      vertx.setTimer(3000L, id -> {
        log.info("start obtain cluster lock.");
        //集群中获取锁，用于独占某些资源, 1秒内获取不到锁则超时，使用getLock时，超时时间默认10秒
        vertx.sharedData().getLockWithTimeout("clusterLock", 1000L, res -> {
          if (res.succeeded()) {
            Lock lock = res.result();
            log.info("obtain cluster lock succeed");
            //注意！使用完毕需要释放锁，否则其他实例无法获取到锁
            vertx.setTimer(10000L, ar -> {
              log.info("cluster lock release");
              lock.release();
            });
          } else {
            log.info("obtain cluster lock failed => {}", res.cause().toString());
          }
        });
      });

      //应用本地锁，应用内资源独占
      vertx.sharedData().getLocalLock("myLocalLock", res -> {
        if (res.succeeded()) {
          Lock lock = res.result();
          log.info("obtain local lock succeed");
          //注意！使用完毕需要释放锁，否则其他实例无法获取到锁
          vertx.setTimer(1000L, ar -> {
            log.info("local lock release");
            lock.release();
          });
        } else {
          log.info("obtain local lock failed");
        }
      });

      startPromise.complete();
    }
  }

}
